package com.hfut.eeg.common.component;

import com.hfut.eeg.common.util.EEGUtil;
import com.hfut.eeg.socket.AiServer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;

/**
 * @author 梁琦
 * @program: eeg
 * @Package com.hfut.eeg.common.component
 * @Description: EEG缓存信息，为单例模式
 * @date 2019-11-23 14:44
 */
@Component
@Scope("singleton")
public class EEGcache implements ApplicationContextAware {

    private static final Logger LOGGER = LoggerFactory.getLogger(EEGcache.class);

    //实现了ApplicationContextAware接口，主要在于EEGThread为原型模式
    private ApplicationContext applicationContext;

    //bean注入
    @Autowired
    private EEGThread eegThread;

    @Autowired
    private AiServer aiServer;


    //EEG的缓存池，存储上一次得到的EEG数据
    //当数据达到一定额度时，会被写到数据库中
    private ArrayList<ArrayList> cachePool=new ArrayList<>();

    //当缓存池中的数据超过阈值时，将被被存放到数据库中，同时缓存池会被清空
    //默认值是10000
    private int threshold=5000;

    //通道数量
    private static final int nChannel = 16;

    //病人编号，必须要有
    private volatile String patientId = "BH20100102006";

    //通道名称
    private String[] labels = {"Fp1","Fp2","F3","F4","C3","C4","P3","P4","O1","O2","F7","F8","T3","T4","T5","T6"};

    //属性回滚
    public void reset(){
        patientId = null;
    }

    //添加数据到缓存池中
    public synchronized boolean addDataToPool(ArrayList data){
        aiServer.setEegId(patientId);
        if(data==null){
            LOGGER.warn("data should not null");
            return false;
        }
        if(cachePool.size() == 0){
            cachePool=data;
        }else {
            for (int i=0;i<cachePool.size();i++){
                cachePool.get(i).addAll((Collection) data.get(i));
            }
        }
        LOGGER.info("当前EEG缓冲池数据总量："+cachePool.get(0).size());
        if(cachePool.get(0).size()>=threshold){
            try{
                LOGGER.info("EEG缓冲池刷新："+new Date());
                flushPool();
            }catch (Exception e){
                e.printStackTrace();
                return false;
            }
        }
        return true;
    }

    //刷新缓冲池，将数据存入到数据库中
    public synchronized void flushPool(){
        if(cachePool==null || cachePool.size()==0){
            return;
        }
        eegThread = (EEGThread) applicationContext.getBean("eegThread");
        LOGGER.info("cachePool缓存数据量："+cachePool.get(0).size());
        //设置线程的eeg数据拷贝
        eegThread.setCache(EEGUtil.deepCopy(cachePool));

        //执行数据库存放操作
        Thread t = new Thread(eegThread);
        t.start();
        //清空缓冲区
        cachePool.clear();
    }

    //通用set、get方法
    public ArrayList<ArrayList> getCachePool() {
        return cachePool;
    }

    public void setCachePool(ArrayList<ArrayList> cachePool) {
        this.cachePool = cachePool;
    }

    public int getThreshold() {
        return threshold;
    }

    public void setThreshold(int threshold) {
        this.threshold = threshold;
    }

    public static int getnChannel() {
        return nChannel;
    }

    public String getPatientId() {
        return patientId;
    }

    public void setPatientId(String patientId) {
        this.patientId = patientId;
    }

    public String[] getLabels() {
        return labels;
    }

    public void setLabels(String[] labels) {
        this.labels = labels;
    }

    public int getNchannel(){
        return nChannel;
    }

    public EEGThread getEegThread() {
        return eegThread;
    }

    public void setEegThread(EEGThread eegThread) {
        this.eegThread = eegThread;
    }

    //实现引用原型的关键
    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
    }
}
